﻿using Sustainalytics.FileManager;
using Sustainalytics.LongRunningTaskManager.Interface;
using System;
using System.IO;

namespace Sustainalytics.LongRunningTaskManager
{
    /// <summary>
    /// Transformer for transforming file result into file manager result.
    /// </summary>
    public class LongRunningTaskFileResultToFileManagerTransformer : ILongRunningTaskResultTransformer
    {
        private readonly IFileManager _fileManager;

        /// <summary>
        /// Ctor.
        /// </summary>
        /// <param name="fileManager"> File manager. </param>
        public LongRunningTaskFileResultToFileManagerTransformer(IFileManager fileManager)
        {
            this._fileManager = fileManager;
        }


        public ILongRunningTaskResult Process(ILongRunningTaskResult result, LongRunningTaskContext taskContext)
        {
            if (result is LongRunningTaskFileInMemResult)
            {
                LongRunningTaskFileInMemResult fileInMem = result as LongRunningTaskFileInMemResult;

                // process in-memory file
                var res = ProcessFileInMemResult(fileInMem, taskContext);

                return res;
            }

            if (result is LongRunningTaskFileOnDiskResult)
            {
                LongRunningTaskFileOnDiskResult fileOnDisk = result as LongRunningTaskFileOnDiskResult;

                // process file on disk
                var res = ProcessFileOnDiskResult(fileOnDisk, taskContext);

                return res;
            }

            return result;
        }

        private ILongRunningTaskResult ProcessFileInMemResult(LongRunningTaskFileInMemResult fileInMemRes, LongRunningTaskContext taskContext)
        {
            // create contents
            FileContents fileContents = new FileContents(
                filePath: string.Concat(taskContext.Ticket.Identity.Name, "/", fileInMemRes.FileName),
                metadata: new FileMetadata(
                    fileName: fileInMemRes.FileName,
                    mimeType: fileInMemRes.MimeType,
                    dateCreated: DateTime.UtcNow),
                streamAccessor: () => new MemoryStream(fileInMemRes.Contents));

            // add file using file manager
            this._fileManager.AddFile(fileContents);

            // create result
            LongRunningTaskFileManagerResult fileMgrRes = new LongRunningTaskFileManagerResult(
                filePath: fileContents.FilePath,
                fileManager: this._fileManager);

            return fileMgrRes;
        }

        private ILongRunningTaskResult ProcessFileOnDiskResult(LongRunningTaskFileOnDiskResult fileOnDisk, LongRunningTaskContext taskContext)
        {
            string filePath = string.Concat(taskContext.Ticket.Identity.Name, "/", fileOnDisk.FileName);
            // create contents
            FileContents fileContents = new FileContents(
                filePath: filePath,
                metadata: new FileMetadata(
                    fileName: fileOnDisk.FileName,
                    mimeType: fileOnDisk.MimeType,
                    dateCreated: DateTime.UtcNow),
                streamAccessor: () =>
                {
                        // open file stream
                        return File.OpenRead(fileOnDisk.FilePath);
                });

            // add file using file manager
            this._fileManager.AddFile(fileContents);

            // create result
            LongRunningTaskFileManagerResult fileMgrRes = new LongRunningTaskFileManagerResult(
                filePath: filePath,
                fileManager: this._fileManager);

            return fileMgrRes;
        }
    }
}
